[Day07]承接[Day06]的內容,繼續講解第四到第八部份。
接觸在ANSA內也是一種Entity
。我們建立一個contact
的Entity
,其element type
是CONTACT
。fields
內的Name
,取名為box drop
,TYPE
則輸入常用的AUTOMATIC_SURFACE_TO_SURFACE
。
至於contact
的master
及slave
的type
(即MSTYP
及SSTYP
),我們都選擇用part set
,此時先前建立的plate_set
及box_set
就派上用場了。我們利用Entity
的_id
這個attribute
,將plate_set
的id
指定給MSID
,box_set
的id
指定給SSID
。
contact = base.CreateEntity(deck, 'CONTACT', {'Name': 'box drop',
'TYPE': 'AUTOMATIC_SURFACE_TO_SURFACE',
'SSID': box_set._id,
'MSID': plate_set._id,
'SSTYP': '2: Part set',
'MSTYP': '2: Part set'})
我們利用base.CreateEntity
建立邊界條件及初始速度。沒錯,在ANSA裡,這些東西也是Entity
。
邊界條件是固定整個plate
,element type
是BOUNDARY_SPC(SET)
,fields
的NSID
設定為plate_set
的id
,c
則設定為123456
,即三個平移及三個旋轉自由度都固定。
初始速度是賦予整個box
一個初速,element type
是INITIAL_VELOCITY_SET
,fields
的VZ
設為-500
,即向下500mm/s
的初速。
# BOUNDARY_SPC(SET)
base.CreateEntity(deck, 'BOUNDARY_SPC(SET)',
{'NSID': plate_set._id, 'c': '123456'})
# INITIAL_VELOCITY_SET
base.CreateEntity(deck, 'INITIAL_VELOCITY_SET',
{'NSID': box_set._id, 'VZ': -500})
我們分別要設定*CONTROL_TERMINATION
及*DATABASE_D3PLOT
兩張卡片。CONTROL
跟DATABASE
開頭的控制卡片,如果是手動在GUI環境內可以輕鬆設定,但是自動化卻也搞了我們一陣子才成功,在此無私分享啦!
*CONTROL_TERMINATION
是用來告訴LS-DYNA,這個模擬的世界你想模擬多長時間。依照一貫的思路,我們可能起手式就會想要找出element type
,然候把想輸入的值包一包丟進fields
。
但很不幸的,對於CONTROL
跟DATABASE
這兩類卡片,並不能這樣。原因是CONTROL
下還有很多種類,TERMINATION
只是其中一種,所以我們的作法是在建立control Entity
的時候,先把想要的種類設成ON
。具體的作法是建立一個ct_fields
的dict
,key
是TERMINATION
,value
是ON
,然候傳入base.CreateEntity
去建立一個control
的ent
,命名為ct_ent
。
再來我們透過ct_ent
的set_entity_values
來定義結束時間ENDTIM
為1.5E-2
秒,問題應該就解決了吧?抱歉,這邊是另外一個坑呀,這樣做竟然行不通呀!
經過我們一番努力之後,發現真正的作法是要將想輸入的值都prefix TERMINATION_
,這就是為什麼我們要做ct_fields.update
的原因。雖然現在看只是寥寥數字,但字字都是汗水,實打實的乾貨。
# *CONTROL_TERMINATION
ct_fields = {'TERMINATION': 'ON'}
ct_ent = base.CreateEntity(deck, 'CONTROL', ct_fields)
ct_fields_ = {'ENDTIM': 1.5E-2}
ct_fields.update({'TERMINATION_' + k: v
for k, v in ct_fields_.items()})
ct_ent.set_entity_values(deck, fields=ct_fields)
*DATABASE_D3PLOT
是用來告訴LS-DYNA,這個模擬的世界你想多久輸出一次數據。我們依樣畫葫蘆,將DT
設為2E-4
秒。
# *DATABASE_D3PLOT
db_fields = {'D3PLOT': 'ON'}
db_ent = base.CreateEntity(deck, 'DATABASE', db_fields)
db_fields_ = {'DT': 2E-4}
db_fields.update({'D3PLOT_' + k: v
for k, v in db_fields_.items()})
db_ent.set_entity_values(deck, fields=db_fields)
到目前為止,我們已經完成了所有LS-DYNA設定。
雖然上面我們所產生的Entity
都確實存在ANSA內,但是我們必須明確告訴ANSA,哪一些東西是想要輸出的。
如果Entity
是material
或property
,我們需要base.GetEntity
先取得該Entity
再利用Entity
的set_entity_values method
將DEFINED
設為YES
。
如果Entity
是control
或是邊界條件這類型的,則要透過base.SetEntityVisibilityValues
將其設為on
(註1
)。
# Visibility
plate_mat = base.GetEntity(deck, '__MATERIALS__', 1)
plate_mat.set_entity_values(deck, {'DEFINED': 'YES'})
plate_sec = base.GetEntity(deck, '__PROPERTIES__', 1)
plate_sec.set_entity_values(deck, {'DEFINED': 'YES'})
box_mat = base.GetEntity(deck, '__MATERIALS__', 2)
box_mat.set_entity_values(deck, {'DEFINED': 'YES'})
box_sec = base.GetEntity(deck, '__PROPERTIES__', 2)
box_sec.set_entity_values(deck, {'DEFINED': 'YES'})
keys = {'CONTACT',
'INITIAL_VELOCITY_SET',
'BOUNDARY_SPC(SET)'}
base.SetEntityVisibilityValues(deck, {key: 'on'
for key in keys})
接下來我們可以輸出k檔,準備呼叫LS-DYNA求解。這邊我們引入Python內建的pathlib module
內的Path
。Path(__file__).parent
可以找出當前檔案所處資料夾,再利用特有的/
連結'box_drop.k
,最後透過as_posix
取得路徑後,使用base.OutputLSDyna
輸出k檔。
from pathlib import Path
output_lsdyna_path = Path(__file__).parent / 'box_drop.k'
lsdyna_filename = output_lsdyna_path.as_posix()
base.OutputLSDyna(filename=lsdyna_filename)
最後,我們透過subprocess.run
呼叫求解的command
,執行的指令會類似:
/path/to/smp-dyna_s i=/path/to/box_drop.k ncpu=10 memory=1500m d=nodump
以上command
是指使用/path/to/smp-dyna_s
這個solver,使用10
個cpu及1500m
memory來求解/path/to/box_drop.k
這個檔案,並且不寫出dump
檔。
由於我們是使用Ubuntu
系統,Windows
的用戶需要注意路徑的設置。
import subprocess
solver_path = f'{Path.home()}/LS-DYNA/13.0/smp-dyna_s'
lsdyna_file_path = f'i=' + lsdyna_filename
ncpu = 'ncpu=10'
memory = 'memory=1500m'
dump = 'd=nodump'
commands = [solver_path,
lsdyna_file_path,
ncpu,
memory,
dump]
c = ' '.join(commands)
print(c)
subprocess.run(commands)
至此,你已經自動產生一個box drop
的project了。
下圖是我們用LS-PrePost錄的gif動畫。
註1:可能有人會發現,這邊的on
是小寫的。雖然我們測過ON
也是可以,但說明文件內是用小寫,保險起見我們還是跟著說明走。有趣的是,如果你把control
或database
那邊的ON
改成on
就不行了呀...